#include <stdio.h>
#include <sys/time.h>
#include <sched.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <error.h>
#include <stdint.h>
#include <pthread.h>
#include <unistd.h>          // 系统调用相关的函数 close()
#include <string.h>          // strcpy, memset(), and memcpy()
#include <sys/types.h>       // 包含了一些基本的系统数据类型 uint8_t、uint16_t 和 uint32_t
#include <sys/socket.h>      // 与套接字相关的函数和数据结构
#include <netinet/in.h>      // 与 Internet 协议族相关的数据结构
#include <netinet/ip.h>      // IP 协议头部的数据结构
#include <netinet/ip_icmp.h> // 定义了 ICMP 协议头部的数据结构
#include <arpa/inet.h>       // 定义了一些 IP 地址转换函数
#include <sys/ioctl.h>       // 进行输入/输出控制的函数和相关宏
#include <bits/ioctls.h>     // 用于 ioctl() 函数的参数
#include <net/if.h>          // 处理网络接口相关的函数和数据结构
#include <linux/if_ether.h>  // 帧格式 以太网帧的一些常量
#include <linux/if_packet.h> // 用于与套接字相关联的网络接口的数据结构 struct sockaddr_ll
#include <net/ethernet.h>    // 以太网帧的数据结构
#include <errno.h>           // errno, perror()
#include <iostream>

#include "tsmp.h"
#include "ptp.h"

#define ETH_P_DEAN 0x8585 // 自定义的以太网协议 type
#define PACKET_LEN 2048   // 数据包的最大长度为 2048 字节
extern Port_delay port_delay;

void send_frame(int sig, siginfo_t *info, void *context) // 到时触发发送程序, sig判断类型，后续两个参数无用
{
    char *type; // 收到的类型
    uint8_t *ptp; // ptp报文
    int iRet;  // 用来判断是否封装正确
    struct Resp_rec tsmp_resp_req;//  = respRec(); //  接收 respRec() req 的回应 
    struct Resp_rec tsmp_resp_resp;// = respRec(); //  接收 respRec()
    uint64_t t1, t4;

    switch (sig)
    {
    case 10:
        type = "pdelayreq";
        ptp = sendPdelayReq();
        iRet = packSend(ptp);
        if (iRet != 0)
        {
            perror("send error\n");
        }

        tsmp_resp_req = respRec();
        t1 = ((uint64_t)tsmp_resp_req.head.local_time_sec  << 32) | tsmp_resp_req.head.local_time_nanosec;
        port_delay.timestamp_1 = t1;

        printf("message type: %s\n\n", type);
        break;
    case 20:
        type = "pdelayresp";
        ptp = sendPdelayResp();
        iRet = packSend(ptp);
        if (iRet != 0)
        {
            perror("send error\n");
        }

        tsmp_resp_resp = respRec();
        t4 = ((uint64_t)tsmp_resp_resp.head.local_time_sec  << 32) | tsmp_resp_resp.head.local_time_nanosec;
        port_delay.timestamp_3 = t4;

        printf("message type: %s\n\n", type);
        break;
    case 30:
        type = "pdelayrespfollowup";
        ptp = sendPdelayRespFollowUp();
        iRet = packSend(ptp);
        if (iRet != 0)
        {
            perror("send error\n");
        }
        printf("message type: %s\n\n", type);
        break;
    default:
        break;
    }
    return;
}

void receive_ptp() // 在这个函数实现接收PTP
{
    int iRet; // 用来判断是否封装正确
    struct Pack_rec tsmp_pack = packRec(); //  接收
    struct Init_pack init_pack; // 取ptp
    memcpy(&init_pack, &tsmp_pack, sizeof(struct Init_pack));
    uint8_t type = init_pack.ptp_header.message_type;

    switch (type)
    {
    case PtpMsgType::E_PDELAY_REQ:  // 判断接收帧类型，定义在ptp.h里
        iRet = parsePdelayReq(tsmp_pack); // 参数为tsmp封装
        if (iRet == -1)
        {
            std::cout << "parse pdelay req error" << std::endl;
        }
        send_frame(20, NULL, NULL); // 发送pdelay_resp
        send_frame(30, NULL, NULL); // 发送pdelay_resp_follow_up
        break;
    case PtpMsgType::E_PDELAY_RESP:
        iRet = parsePdelayResp(init_pack); // 接收pdelay_resp
        if (iRet == -1)
        {
            std::cout << "parse pdelay resp error" << std::endl;
        }
        break;
    case PtpMsgType::E_PDELAY_RESP_FOLLOW_UP:
        iRet = parsePdelayRespFollowUp(init_pack); // 接收pdelay_resp_follow_up
        if (iRet == -1)
        {
            std::cout << "parse pdelay resp follow up error" << std::endl;
        }
        break;
    default:
        break;
    }
    printf("\n");
}

int main()
{
    printf("ll\n");
    receive_ptp(); // 打开receive
    printf("ll\n");
    return 0;
}